package com.seedwill.common.query.filter;

import java.io.Serializable;
import java.util.Collection;

/**
 * JDBC查询表达式
 * 
 * @author KDYI
 * 
 */
public class Expression implements Serializable{

	public static final int EQUALTO = 0;

	public static final int NOTEQUALTO = 1;

	public static final int GREATEROREQUAL = 2;

	public static final int GREATERTHAN = 3;

	public static final int LESSOREQUAL = 4;

	public static final int LESSTHAN = 5;

	public static final int BETWEEN = 6;

	public static final int NOTBETWEEN = 7;

	public static final int IN = 8;

	public static final int NOTIN = 9;

	public static final int LIKE = 10;

	public static final int NOTLIKE = 11;

	public static final int ISNULL = 12;

	public static final int NOTNULL = 13;

	public static final int AND = 14;

	public static final int OR = 15;

	public static final int NOT = 16;

	public static final int CLAUSE = 17;

	/**
	 * like %xx
	 */
	public static final int LEFTLIKE = 100;

	/**
	 * not like %xx
	 */
	public static final int NOTLEFTLIKE = 101;
	
	/**
	 * like xx%
	 */
	public static final int RIGHTLIKE = 102;

	/**
	 * not like xx%
	 */
	public static final int NOTRIGHTLIKE = 103;
	
	/**
	 * sql 条件语句
	 */
	public static final int SQLCLAUSE = 104;
	
	/**
	 * 置于from 后， order by前的sql语句
	 */
	public static final int QUERYTAILER = 105;
	
	static String like = "like";
	static String not_like = "not like";
	static String empty = "";
	
	public static final String[] SQL = new String[24];

	static {
		SQL[EQUALTO] = "=";
		SQL[NOTEQUALTO] = "!=";
		SQL[GREATEROREQUAL] = ">=";
		SQL[GREATERTHAN] = ">";
		SQL[LESSOREQUAL] = "<=";
		SQL[LESSTHAN] = "<";
		SQL[BETWEEN] = "between";
		SQL[NOTBETWEEN] = "not between";
		SQL[IN] = "in";
		SQL[NOTIN] = "not in";
		SQL[LIKE] = "like";
		SQL[NOTLIKE] = "not like";
		SQL[ISNULL] = "is null";
		SQL[NOTNULL] = "is not null";
		SQL[AND] = "and";
		SQL[OR] = "or";
		SQL[NOT] = "not";
		SQL[CLAUSE] = "";
		
		SQL[LEFTLIKE] = like;
		SQL[NOTLEFTLIKE] = not_like;
		SQL[RIGHTLIKE] = like;
		SQL[NOTRIGHTLIKE] = not_like;
		SQL[SQLCLAUSE] = empty;
		SQL[QUERYTAILER] = empty;
	}

	private String join;
	
	private String field;

	private Object value;

	protected int operator;

	protected Expression() {

	}

	protected Expression(String field, Object value) {
		setField(field);
		setValue(value);
	}

	/**
	 * @return Returns the field.
	 */
	public String getField() {
		return field;
	}

	/**
	 * @param field
	 *            The field to set.
	 */
	public void setField(String field) {
		this.field = field;
	}

	/**
	 * @return Returns the operator.
	 */
	public int getOperator() {
		return operator;
	}

	public String getSQLOperator() {
		return SQL[operator];
	}

	/**
	 * @param operator
	 *            The operator to set.
	 */
	public void setOperator(int operator) {
		this.operator = operator;
	}

	/**
	 * @return Returns the value.
	 */
	public Object getValue() {
		return value;
	}

	/**
	 * @param value
	 *            The value to set.
	 */
	public void setValue(Object value) {
		this.value = value;
	}

	public static Expression equal(String field, Object value) {
		return new Equal(field, value);
	}

	public static Expression notEqual(String field, Object value) {
		return new NotEqual(field, value);
	}

	public static Expression greaterOrEqual(String field, Object value) {
		return new GreaterOrEqual(field, value);
	}

	public static Expression greaterThan(String field, Object value) {
		return new GreaterThan(field, value);
	}

	public static Expression lessOrEqual(String field, Object value) {
		return new LessOrEqual(field, value);
	}

	public static Expression lessThan(String field, Object value) {
		return new LessThan(field, value);
	}

	public static Expression like(String field, String value) {
		return new Like(field, value);
	}

	public static Expression notLike(String field, String value) {
		return new NotLike(field, value);
	}

	public static Expression in(String field, Collection value) {
		return new In(field, value);
	}

	public static Expression notIn(String field, Collection value) {
		return new NotIn(field, value);
	}

	public static Expression nullField(String field, Object value) {
		return new Null(field, value);
	}

	public static Expression notNullField(String field, Object value) {
		return new NotNull(field, value);
	}

	public static Expression between(String field, Object low, Object high) {
		return new Between(field, new Object[] { low, high });
	}

	public static Expression notBetween(String field, Object low, Object high) {
		return new NotBetween(field, new Object[] { low, high });
	}

	public static Expression and(Expression lexp, Expression rexp) {
		return new AndExpression(lexp, rexp);
	}

	public static Expression or(Expression lexp, Expression rexp) {
		return new OrExpression(lexp, rexp);
	}

	public static Expression not(Expression exp) {
		return new NotExpression(exp);
	}

	public static Expression clause(String field, Object...objects) {
		return new ClauseExpression(field, objects);
	}
	
	public static Expression leftLike(final String field, final Object value) {
		return new LEFTLIKE(field, value);
	}
	public static Expression notLeftLike(final String field, final Object value) {
		return new NOTLEFTLIKE(field, value);
	}
	public static Expression rightLike(final String field, final Object value) {
		return new RIGHTLIKE(field, value);
	}
	public static Expression notRightLike(final String field, final Object value) {
		return new NOTRIGHTLIKE(field, value);
	}
	public static Expression sqlClause(final String clause, final Object value) {
		return new SQLCLAUSE(clause, value);
	}
	public static Expression queryTailer(final String clause, final Object value) {
		return new QUERYTAILER(clause, value);
	}

	private static class Equal extends Expression {
		/**
		 * @param field
		 * @param value
		 */
		private Equal(String field, Object value) {
			super(field, value);
			setOperator(EQUALTO);
		}

	}

	private static class NotEqual extends Expression {

		/**
		 * @param field
		 * @param value
		 */
		private NotEqual(String field, Object value) {
			super(field, value);
			setOperator(NOTEQUALTO);
		}

	}

	private static class GreaterOrEqual extends Expression {

		/**
		 * @param field
		 * @param value
		 */
		private GreaterOrEqual(String field, Object value) {
			super(field, value);
			setOperator(GREATEROREQUAL);
		}

	}

	private static class GreaterThan extends Expression {

		/**
		 * @param field
		 * @param value
		 */
		private GreaterThan(String field, Object value) {
			super(field, value);
			setOperator(GREATERTHAN);
		}

	}

	private static class LessOrEqual extends Expression {

		/**
		 * @param field
		 * @param value
		 */
		public LessOrEqual(String field, Object value) {
			super(field, value);
			setOperator(LESSOREQUAL);
		}

	}

	private static class LessThan extends Expression {

		/**
		 * @param field
		 * @param value
		 */
		public LessThan(String field, Object value) {
			super(field, value);
			setOperator(LESSTHAN);
		}

	}

	private static class Null extends Expression {

		/**
		 * @param field
		 * @param value
		 */
		public Null(String field, Object value) {
			super(field, value);
			setOperator(ISNULL);
		}

	}

	private static class NotNull extends Expression {

		/**
		 * @param field
		 * @param value
		 */
		public NotNull(String field, Object value) {
			super(field, value);
			setOperator(NOTNULL);
		}

	}

	private static class In extends Expression {

		/**
		 * @param field
		 * @param value
		 */
		public In(String field, Object value) {
			super(field, value);
			setOperator(IN);
		}

	}

	private static class NotIn extends Expression {

		/**
		 * @param field
		 * @param value
		 */
		public NotIn(String field, Object value) {
			super(field, value);
			setOperator(NOTIN);
		}

	}

	private static class Between extends Expression {

		/**
		 * @param field
		 * @param value
		 */
		public Between(String field, Object value) {
			super(field, value);
			setOperator(BETWEEN);
		}

	}

	private static class NotBetween extends Expression {

		/**
		 * @param field
		 * @param value
		 */
		public NotBetween(String field, Object value) {
			super(field, value);
			setOperator(NOTBETWEEN);
		}

	}

	private static class Like extends Expression {

		/**
		 * @param field
		 * @param value
		 */
		public Like(String field, String value) {
			super(field, value);
			setOperator(LIKE);
		}

	}

	private static class NotLike extends Expression {

		/**
		 * @param field
		 * @param value
		 */
		public NotLike(String field, String value) {
			super(field, value);
			setOperator(NOTLIKE);
		}

	}

	public static class LogicalExpression extends Expression {
		private final Expression exp_l, exp_r;

		/**
		 * @param field
		 * @param value
		 */
		protected LogicalExpression(Expression left, Expression right) {
			exp_l = left;
			exp_r = right;
		}

		public Expression getLeftExpression() {
			return exp_l;
		}

		public Expression getRightExpression() {
			return exp_r;
		}
	}

	public static class AndExpression extends LogicalExpression {

		/**
		 * @param left
		 * @param right
		 */
		private AndExpression(Expression left, Expression right) {
			super(left, right);
			setOperator(AND);
		}
	}

	public static class OrExpression extends LogicalExpression {

		/**
		 * @param field
		 * @param value
		 */
		private OrExpression(Expression left, Expression right) {
			super(left, right);
			setOperator(OR);
		}
	}

	public static class NotExpression extends Expression {
		private final Expression exp;

		/**
		 * @param field
		 * @param value
		 */
		private NotExpression(Expression exp) {
			this.exp = exp;
			setOperator(NOT);
		}

		public Expression getExpression() {
			return exp;
		}
	}

	public static class ClauseExpression extends Expression {
		public ClauseExpression(String field,  Object...objects) {
			
			super(field, objects);
			
			//System.out.println("\n ClauseExpression: para len: " + objects.length);
			
			setOperator(CLAUSE);
		}
	}
	
	private static class LEFTLIKE extends Expression {
		private LEFTLIKE(final String field, final Object value) {
			super(field, value);
			setOperator(LEFTLIKE);
		}

	}
	private static class NOTLEFTLIKE extends Expression {
		private NOTLEFTLIKE(final String field, final Object value) {
			super(field, value);
			setOperator(NOTLEFTLIKE);
		}

	}
	private static class RIGHTLIKE extends Expression {
		private RIGHTLIKE(final String field, final Object value) {
			super(field, value);
			setOperator(RIGHTLIKE);
		}

	}
	private static class NOTRIGHTLIKE extends Expression {
		private NOTRIGHTLIKE(final String field, final Object value) {
			super(field, value);
			setOperator(NOTRIGHTLIKE);
		}

	}
	
	private static class SQLCLAUSE extends Expression {
		private SQLCLAUSE(final String field, final Object value) {
			super(field, value);
			setOperator(SQLCLAUSE);
		}

	}
	private static class QUERYTAILER extends Expression {
		private QUERYTAILER(final String field, final Object value) {
			super(field, value);
			setOperator(QUERYTAILER);
		}

	}
	
	protected static final String andJoin = "and";
	protected static final String orJoin = "or";
	
	
	public String getJoin() {
		if(join == null){
			return andJoin;
		}else{
			return join;
		}
	}

	public void setJoin(String join) {
		this.join = join;
	}

}
